/**
 * @description table 页面操作方法封装
 * @param {Function} api 获取表格数据 api 方法 (必传)
 * @param {Object} initParam 获取数据初始化参数 (非必传，默认为{})
 * @param {Boolean} openPage 是否有分页 (非必传，默认为true)
 * @param {Function} beforeSearch 查询前的回调函数
 * @param {Function} dataCallBack 对后台返回的数据进行处理的方法 (非必传)
 * @param {Function} requestError 请求出错后的回调函数
 * @param {Object[]} columns 表格的列配置项
 * @param {Function} enumCallBack 字典设置的回调函数，ProTable 内置函数
 */
export const useTable = (
  api?: (params: any) => Promise<any>,
  initParam: object = {},
  isPageable: boolean = true,
  beforeSearch?: (searchParam: any) => any,
  dataCallBack?: (data: any) => any,
  requestError?: (error: any) => void,
  columns?: EcoTable.Column[]
) => {
  const state = reactive<EcoTable.StateProps>({
    // 表格数据
    tableData: [],
    // 分页数据
    pageable: {
      // 当前页数
      pageNum: 1,
      // 每页显示条数
      pageSize: 20,
      // 一页显示多少条数据
      pageSizes: [10, 20, 50, 100, 200],
      // 总条数
      total: 0
    },
    // 查询参数（只包括查询）
    searchParam: {},
    // 初始化默认的查询参数，重置时候用到
    searchInitParam: {},
    // 总参数（包含分页和查询参数)
    totalParam: {}
  })

  /**
   * @description 分页查询参数（只包括分页和表格字段排序，其他排序方式可自行配置）
   */
  const pageParam = computed({
    get: () => {
      return { pageNum: state.pageable.pageNum, pageSize: state.pageable.pageSize }
    },
    set: (newVal: any) => {
      console.log('分页更新值', newVal)
    }
  })

  /**
   * @description 获取表格数据
   * @return void
   */
  const getTableList = async (requestParam: object = initParam) => {
    if (!api) return
    try {
      // 先把初始化参数和分页参数放到总参数里面
      Object.assign(state.totalParam, requestParam, isPageable ? pageParam.value : {})
      let searchParam = { ...state.searchInitParam, ...state.totalParam } as any
      beforeSearch && (searchParam = beforeSearch(searchParam) ?? searchParam)

      // 返回 false 则不执行查询
      if (searchParam === false) return

      // 触发每个配置项的 beforeSearch
      if (columns) {
        for (let i = 0; i < columns.length; i++) {
          const col = columns[i]
          if (col.search?.beforeSearch) {
            searchParam[col.prop!] = col.search?.beforeSearch(searchParam[col.search.key ?? col.prop!], searchParam, col) ?? searchParam[col.prop!]

            if (searchParam[col.prop!] === false) return
          }
        }
      }

      // 请求数据
      let { data } = await api(searchParam)

      dataCallBack && (data = dataCallBack(data) || data)
      if (data) state.tableData = isPageable ? data.list : data.list || data

      // 解构后台返回的分页数据 (如果有分页更新分页信息)
      if (isPageable) {
        const { pageNum, pageSize, pageSizes, total } = data
        if (pageNum) updatePaging({ pageNum })
        if (pageSize) updatePaging({ pageSize })
        if (pageSizes) updatePaging({ pageSizes })
        if (total) updatePaging({ total })
        else updatePaging({ total: data.length })
      }
    } catch (error) {
      console.error(error)
      requestError && requestError(error)
    }
  }

  /**
   * @description 更新查询参数
   * @param {Object} model 查询参数对象
   * @param {Boolean} removeNoValue 是否去除空值项，true 去除，false 不去除。默认为 true
   * @return void
   */
  const updatedTotalParam = (model?: Record<string, any>, removeNoValue = true) => {
    state.totalParam = {}

    // 如果 model 存在且不清除空值项
    if (model && !removeNoValue) return Object.assign(state.totalParam, model, isPageable ? pageParam.value : {})

    // 如果去除空值项
    if (removeNoValue) {
      const nowSearchParam: EcoTable.StateProps['searchParam'] = model || state.searchParam
      // 防止手动清空输入框携带参数（这里可以自定义查询参数前缀）
      for (const key in state.searchParam) {
        const val = state.searchParam[key]
        // 过滤空值
        if (val !== '' && val !== null && val !== undefined) nowSearchParam[key] = val
      }

      return Object.assign(state.totalParam, nowSearchParam, isPageable ? pageParam.value : {})
    }

    return Object.assign(state.totalParam, model || state.searchParam, isPageable ? pageParam.value : {})
  }

  /**
   * @description 更新分页信息
   * @param {Object} pageable 后台返回的分页数据
   * @return void
   */
  const updatePaging = (pageable: Partial<EcoTable.Pageable>) => {
    Object.assign(state.pageable, pageable)
  }

  /**
   * @description 表格数据查询
   * @param {Object} model 查询参数对象
   * @param {Boolean} removeNoValue 是否去除空值项，true 去除，false 不去除。默认为 true
   * @return void
   */
  const search = (model?: Record<string, any>, removeNoValue = true) => {
    state.pageable.pageNum = 1
    // 更新查询参数
    updatedTotalParam(model, removeNoValue)
    getTableList()
  }

  /**
   * @description 表格数据重置
   * @param {Object} model 查询参数对象
   * @param {Boolean} removeNoValue 是否去除空值项，true 去除，false 不去除。默认为 true
   * @return void
   */
  const reset = (model?: Record<string, any>, removeNoValue = true) => {
    state.pageable.pageNum = 1
    state.searchParam = {}
    // 重置搜索表单的时，如果有默认搜索参数，则重置默认的搜索参数
    state.searchParam = { ...state.searchInitParam }
    // 更新查询参数
    updatedTotalParam(model, removeNoValue)
    getTableList()
  }

  /**
   * @description 每页条数改变
   * @param {Number} paging 当前分页信息
   * @return void
   */
  const handlePagination = (pageable: Partial<EcoTable.Pageable>) => {
    if (pageable.pageNum) state.pageable.pageNum = pageable.pageNum
    if (pageable.pageSize) state.pageable.pageSize = pageable.pageSize
    if (pageable.pageSizes) state.pageable.pageSizes = pageable.pageSizes
    if (isPageable) getTableList()
  }

  return {
    ...toRefs(state),
    getTableList,
    search,
    reset,
    handlePagination,
    updatedTotalParam
  }
}
